package cn.edu.scnu.match.service;

import cn.edu.scnu.exception.CreateException;
import cn.edu.scnu.exception.SaveException;
import cn.edu.scnu.match.mapper.MatchMapper;
import cn.edu.scnu.match.mapper.RegisterMapper;
import cn.edu.scnu.pojo.MatchActivity;
import cn.edu.scnu.pojo.RegistrationForm;
import cn.edu.scnu.pojo.User;
import cn.edu.scnu.utils.LoginUtils;
import cn.edu.scnu.utils.PrefixKey;
import cn.edu.scnu.vo.MatchStatus;
import cn.edu.scnu.vo.PaymentStatus;
import cn.edu.scnu.vo.UserTypes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import redis.clients.jedis.JedisCluster;

import java.util.List;
import java.util.UUID;

@Service
public class RegisterService {
    @Autowired
    private RegisterMapper registerMapper;
    @Autowired
    private MatchMapper matchMapper;
    @Autowired
    private JedisCluster jedis;

    @Transactional(rollbackFor = Exception.class)
    public void registerMatch(RegistrationForm form) throws CreateException {
        // 判断登录用户是否有权限报名
        User user = LoginUtils.getUserInfo();
        if(user.getType() != UserTypes.PERSONAL.type) {
            throw new CreateException("用户无权限报名");
        }
        // 查询该用户是否已经报名该赛事
//        int exist = registerMapper.queryRegisterByUserAndMatch(form);
        int exist = 0;
        if (exist == 0) {
            // 未报名该赛事
            // 判断是否达到当前报名人数限制
            MatchActivity match = matchMapper.getMatchById(form.getMatchId());
            if (match.getStatus() == MatchStatus.REGISTER_NOWS.status) {
                // 生成报名编号
                String registerId = UUID.randomUUID().toString();
                form.setId(registerId);
                try {
                    // 判断报名表的类型
                    if(match.getEntryFee() == 0) {
                        form.setStatus(PaymentStatus.FREE.paymentStatus);
                    } else if (match.getEntryFee() > 0) {
                        form.setStatus(PaymentStatus.UNPAID.paymentStatus);
                    }
                    // 创建报名表
                    registerMapper.registerMatch(form);

                    // 修改赛事的报名人数
                    String matchKey = PrefixKey.MATCH_QUERY_PREFIX + form.getMatchId();
                    String lock = PrefixKey.MATCH_UPDATE_PREFIX + form.getMatchId() + ".lock";

                    // 判断是否存在该赛事的锁，如果存在，则期间不允许修改
                    if(jedis.exists(lock)) {
                        throw new CreateException("当前系统繁忙，请稍后尝试");
                    }
                    // 更新前删除缓存
                    Long remainTime = 60000L;
                    if(jedis.exists(matchKey)) {
                        remainTime = jedis.ttl(matchKey);
                        jedis.del(matchKey);
                    }

                    // 加锁
                    jedis.setex(lock, Integer.parseInt(remainTime + ""), "");   // 设置超时时间为旧数据存在的剩余时间
                    matchMapper.addNumber(form.getMatchId());
                    if(match.getNumber() + 1 >= match.getMaxNumber()) {
                        System.out.println("名额超限");
                        match.setStatus(MatchStatus.EXCEEDED_QUOTA.status);
                        matchMapper.saveMatch(match);
                    }

                    // 将锁释放
                    jedis.del(lock);
                } catch (Exception e) {
                    // 数据库回滚操作
                    e.printStackTrace();
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    throw new RuntimeException("报名失败");
                }
            } else if (match.getStatus() == MatchStatus.EXCEEDED_QUOTA.status) {
                // 报名人数已满
                throw new CreateException("报名人数已满");
            } else if(match.getStatus() == MatchStatus.ENROLLING_SOON.status) {
                throw new CreateException("报名尚未开始，请耐心等待");
            } else if(match.getStatus() == MatchStatus.REGISTRATION_ENDS.status) {
                throw new CreateException("报名已结束");
            }
        } else {
            // 已报名该赛事
            throw new CreateException("您已报名该赛事");
        }
    }

    public void saveRegisteration(RegistrationForm form) {
        registerMapper.saveRegisteration(form);
    }

    public List<RegistrationForm> getRegisterationsByUserId(String userId) {
        return registerMapper.getRegistersByUserId(userId);
    }

    public void payForEntry(String entryId) {
        try {
            registerMapper.payForEntry(entryId);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
